#include "StartupDlg.h"

#include <core/ImageMgr.h>
#include <core/StyleMgr.h>
#include <core/common_types.h>
#include <qbkernel/include/qb_base.h>
#include <qbprotocol/include/rdClientLocal.h>
#include <qbprotocol/include/ssCmnDefine.h>
#include <widgets/SCheckEx.h>
#include <widgets/SImageButton.h>
#include <widgets/SLineEdit.h>
#include <widgets/SPopupWindow.h>

#include <QAbstractItemView>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
#include <QMessageBox>
#include <QMouseEvent>
#include <QPushButton>
#include <QStylePainter>
#include <QVBoxLayout>

#include "../ServerInfo.h"
#include "../login/auth_login.h"
#include "FadeTips.h"
#include "FindPasswordDlg.h"
#include "LoginProgressBtn.h"
#include "ProxySettingDlg.h"
#include "QrLoginWidget.h"
#include "ServerComboBox.h"

using namespace qb;
enum ButtonId { Setting, Min, Close, Scan };

static const int s_border_width = 1;
StartupDlg::StartupDlg(QWidget* parent /*= nullptr*/) : QDialog(parent) {
  setWindowFlag(Qt::FramelessWindowHint);
  setAttribute(Qt::WA_TranslucentBackground);
  resize(900, 640);
  setContentsMargins(0, 0, 0, 0);

  connect(this, &StartupDlg::notifyErrorMsg, this, &StartupDlg::showErrorMsg);

  QHBoxLayout* mainLayout = new QHBoxLayout(this);
  mainLayout->setSpacing(0);
  mainLayout->setContentsMargins(4, 4, 4, 4);
  // 左侧账号信息
  m_leftLayout = new QVBoxLayout();
  m_leftLayout->setSpacing(0);
  m_leftLayout->setContentsMargins(64, 0, 0, 0);  // 左侧空白
  m_leftLayout->addStretch();
  QLabel* logo = new QLabel(this);
  SImage* logoImg = ImgMgr::instance().image("guiframe_app_logo");
  if (logoImg) logo->setPixmap(QPixmap::fromImage(*logoImg));
  m_leftLayout->addWidget(logo);
  m_leftLayout->addSpacing(12);

  m_loginSettingWidget = new QWidget(this);
  m_leftLayout->addWidget(m_loginSettingWidget);

  QVBoxLayout* loginSettingsLayout = new QVBoxLayout();
  loginSettingsLayout->setContentsMargins(0, 0, 0, 0);
  m_loginSettingWidget->setLayout(loginSettingsLayout);

  loginSettingsLayout->setSpacing(0);
  m_editUser = new SLineEdit("", this);
  m_editUser->setSelectAllWhenFocus(true);
  m_editUser->setFixedSize(240, 40);
  m_editUser->setPlaceholderText(tr("请输入用户名/手机号"));
  QFont f = m_editUser->font();
  f.setPixelSize(15);
  m_editUser->setFont(f);

  LoginUserInfo lui = QuoteServerInfo::instance().userInfo();
  if (!lui.strUser.empty())
    m_editUser->setText(QString::fromStdString(lui.strUser));  // UTF-8?

  loginSettingsLayout->addWidget(m_editUser);
  loginSettingsLayout->addSpacing(16);

  m_editPwd = new SLineEdit("", this);
  m_editPwd->setFixedSize(240, 40);
  m_editPwd->setPlaceholderText(tr("请输入密码"));
  m_editPwd->setSelectAllWhenFocus(true);
  m_editPwd->setEchoMode(QLineEdit::Password);
  m_editPwd->setFont(f);
  loginSettingsLayout->addWidget(m_editPwd);
  loginSettingsLayout->addSpacing(16);
  if (lui.savePwd && !lui.strPwd.empty())
    m_editPwd->setText(QString::fromStdString(lui.strPwd));

  m_loginBtn = new LoginProgressBtn(this);
  m_loginBtn->setFixedSize(240, 40);
  loginSettingsLayout->addWidget(m_loginBtn);
  loginSettingsLayout->addSpacing(66);
  connect(m_loginBtn, &LoginProgressBtn::clicked, this, &StartupDlg::login);

  m_cbServers = new ServerCombox(this);
  m_cbServers->setFixedSize(240, 24);
  m_cbServers->setFocusPolicy(Qt::NoFocus);
  updateServerList();
  loginSettingsLayout->addWidget(m_cbServers);
  loginSettingsLayout->addSpacing(8);

  m_rememberPwd = new SCheckEx(tr("记住密码"), this);
  m_rememberPwd->setFixedSize(240, 24);
  m_rememberPwd->setFocusPolicy(Qt::NoFocus);
  loginSettingsLayout->addWidget(m_rememberPwd);
  loginSettingsLayout->addSpacing(8);
  if (lui.savePwd) m_rememberPwd->setSelectState(Qt::Checked, false);

  m_autoStart = new SCheckEx(tr("开机启动"), this);
  m_autoStart->setFixedSize(240, 24);
  m_autoStart->setFocusPolicy(Qt::NoFocus);
  loginSettingsLayout->addWidget(m_autoStart);
  loginSettingsLayout->addSpacing(8);
  if (lui.autoRun) m_autoStart->setSelectState(Qt::Checked, false);

  QString str = tr("忘记密码?");
  str =
      QString("<a href=\"http://www.baidu.com\"><font color=#%1>%2</font></a>")
          .arg(StyleMgr::instance().color("TitleWord").rgb(), 0, 16)
          .arg(str);
  lbForget = new QLabel(str, this);
  lbForget->setFixedSize(240, 24);
  lbForget->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
  loginSettingsLayout->addWidget(lbForget);
  lbForget->installEventFilter(this);
  loginSettingsLayout->addSpacing(4);

  m_scanWidget = new QrLoginWidget(this);
  m_scanWidget->hide();
  m_leftLayout->addWidget(m_scanWidget);

  str = tr("联系我们 400-119-9898");
  str = QString("<font color=#%1>%2</font>")
            .arg(StyleMgr::instance().color("TitleWord").rgb(), 0, 16)
            .arg(str);
  QLabel* lbContract = new QLabel(str, this);
  lbContract->setFixedSize(240, 24);
  lbContract->setAlignment(Qt::AlignRight);
  m_leftLayout->addWidget(lbContract);

  m_leftLayout->addStretch();
  mainLayout->addLayout(m_leftLayout);

  // 标题栏
  QHBoxLayout* titleLayout = new QHBoxLayout();
  titleLayout->setAlignment(Qt::AlignTop);
  titleLayout->setSpacing(4);

  titleLayout->addStretch();
  m_loginSettingBtn = new SImageButton(this, "auth_login_setting");
  m_loginSettingBtn->setIndex(Setting);
  titleLayout->addWidget(m_loginSettingBtn);
  connect(m_loginSettingBtn, &SImageButton::clicked, this, [this](int) {
    QMenu* menu = new QMenu();
    menu->setAttribute(Qt::WA_DeleteOnClose);
    menu->addAction("网络设置", this, [=]() {
      ProxySettingDlg w(this);
      w.resize(474, 410);
      w.exec();
    });
    menu->popup(mapToGlobal(m_loginSettingBtn->geometry().bottomLeft()));
  });

  SImageButton* ib = new SImageButton(this, "guiframe_app_min");
  ib->setIndex(Min);
  titleLayout->addWidget(ib);
  connect(ib, &SImageButton::clicked, this,
          [this](int) { setWindowState(Qt::WindowState::WindowMinimized); });

  ib = new SImageButton(this, "guiframe_app_close");
  ib->setIndex(Close);
  titleLayout->addWidget(ib);
  connect(ib, &SImageButton::clicked, this, [this](int) { reject(); });

  mainLayout->addLayout(titleLayout);

  setLayout(mainLayout);
  setTabOrder(m_editUser, m_editPwd);
  setTabOrder(m_editPwd, m_editUser);

  m_loginModeBtn = new SImageButton(this, "auth_login_qrcode");
  m_loginModeBtn->setIndex(Scan);
  m_loginModeBtn->setEnabled(false);
  m_loginModeBtn->setToolTip("敬请期待");
  connect(m_loginModeBtn, &SImageButton::clicked, this,
          &StartupDlg::onBtnClicked);

  qbBase::getMessageKernel()->RegisterMessageKernelObserver(this);
  connect(this, &StartupDlg::notifyProgress, this, &StartupDlg::OnProgress);
  m_loginBtn->setFocus();
}

QWidget* StartupDlg::serverList() { return m_cbServers; }

void StartupDlg::paintEvent(QPaintEvent* event) {
  QStylePainter painter(this);
  painter.setRenderHint(QPainter::Antialiasing);
  painter.setBrush(QBrush(StyleMgr::instance().color("ElementBackground")));

  QPen pen(StyleMgr::instance().color("InnerBorder"), s_border_width);
  painter.setPen(pen);
  painter.drawRoundedRect(rect(), StyleMgr::instance().size("RoundCorner"),
                          StyleMgr::instance().size("RoundCorner"));
  QPen pen2(StyleMgr::instance().color("InnerBorder"), 2);
  painter.setPen(pen2);
  painter.drawRect(rect().adjusted(2, 2, -2, -2));

  SImage* bkImage = ImgMgr::instance().image(
      "auth_login_bk_default", WidgetStatus::kNormal, devicePixelRatioF());
  if (bkImage) {
    int imgWidth = bkImage->width();
    QRect imgRect = rect();
    imgRect.adjust(0, 3, -3, -3);
    imgRect.setLeft(imgRect.width() - imgWidth);
    painter.setRenderHint(QPainter::SmoothPixmapTransform);  // 处理图片失真
    painter.drawImage(imgRect, *bkImage);
  }
}

void StartupDlg::resizeEvent(QResizeEvent*) {
  QSize s = m_loginModeBtn->sizeHint();
  QRect r(0, 0, s.width(), s.height());
  r.moveBottomLeft(rect().bottomLeft() + QPoint(14, -14));
  m_loginModeBtn->setGeometry(r);
}

bool StartupDlg::eventFilter(QObject* watched, QEvent* event) {
  if (watched == lbForget && event->type() == QEvent::MouseButtonPress) {
    QMouseEvent* me = static_cast<QMouseEvent*>(event);
    if (me->button() == Qt::LeftButton) {
      // 点击忘记密码
      FindPasswordDlg* findPwdDlg = new FindPasswordDlg(this);
      findPwdDlg->resize(480, 480);
      connect(findPwdDlg, &FindPasswordDlg::clearStartPwd, this,
              &StartupDlg::onClearPwd);
      findPwdDlg->exec();
    }
  }
  return QWidget::eventFilter(watched, event);
}

static QPoint s_oldPos;
void StartupDlg::mousePressEvent(QMouseEvent* event) {
  if (event->button() == Qt::LeftButton && childAt(event->pos()) == nullptr) {
    setCursor(Qt::SizeAllCursor);
    s_oldPos = event->globalPos();
    m_dragging = true;
  }
}

void StartupDlg::mouseReleaseEvent(QMouseEvent* event) {
  if (event->button() == Qt::LeftButton) {
    setCursor(Qt::ArrowCursor);
    m_dragging = false;
  }
}

void StartupDlg::mouseMoveEvent(QMouseEvent* event) {
  if (m_dragging && event->buttons() & Qt::LeftButton) {
    QPoint offset = event->globalPos() - s_oldPos;
    move(frameGeometry().topLeft() + offset);
    s_oldPos = event->globalPos();
  }
}

void StartupDlg::keyPressEvent(QKeyEvent* event) {
  if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
    login();
    return;
  }
  QDialog::keyPressEvent(event);
}

void StartupDlg::resetWidget() {
  m_loginSettingWidget->setEnabled(true);
  m_loginBtn->setLoginState(false);
}

void StartupDlg::OnProgress(int progress, int result) {
  m_loginBtn->setLoginProgress(progress);
  if (progress == 100) {
    qbBase::getMessageKernel()->DeRegisterMessageKernelObserver(this);
    log_info("Login Sucess!");
    accept();
  }
}

STDMETHODIMP_(void)
StartupDlg::OnRecvNetStatus(qb::NetStatus status, short retcode) {
  if (retcode == E_RC_OK) {
    switch (status) {
      case qb::eNetStatus_ConnectingLogin:
        notifyProgress(12, 0);
        break;
      case qb::eNetStatus_ConnectedLogin:
        notifyProgress(24, 0);
        break;
      case qb::eNetStatus_VerifyLogin:
        notifyProgress(36, 0);
        break;
      case qb::eNetStatus_ConnectingGW:
        notifyProgress(48, 0);
        break;
      case qb::eNetStatus_ConnectedGW:
        notifyProgress(60, 0);
        break;
      case qb::eNetStatus_VerifyGW:
        notifyProgress(72, 0);
        break;
      case qb::eNetStatus_Authority:
        notifyProgress(84, 0);
        break;
      case qb::eNetStatus_Done:
        notifyProgress(100, 0);
        break;
      default:
        break;
    }
  } else if (retcode < 0) {
    emit notifyErrorMsg(tr("连接服务器失败"));
    //	resetWidget();
  } else {
    if (retcode == E_RC_PASSWD_ERR || retcode == E_RC_USER_ERR) {
      emit notifyErrorMsg(tr("账号或密码错误，请重新输入"));
      resetWidget();
    } else if (retcode == E_RC_NOLOGIN) {
      emit notifyErrorMsg(tr("登录失败，错误码：4，请联系客服"));
    } else if (retcode == E_RC_ERROR) {
      emit notifyErrorMsg(tr("登录失败，错误码：5，请联系客服"));
    } else if (retcode == E_RC_VERSION_CHECK) {
      emit notifyErrorMsg(tr("发现新版本，请更新后登录"));
    } else if (retcode == E_RC_IP_CHECK) {
      emit notifyErrorMsg(tr("您的IP地址与注册不符,请联系客服"));
    } else if (retcode == E_RC_CONN_ERR) {
      emit notifyErrorMsg(tr("由于网络或端口问题连接失败"));
    } else if (retcode == E_RC_COOKIE_ERR) {
      emit notifyErrorMsg(tr("登录超时，请重新登录"));
    } else if (retcode == E_RC_MAC_CHECK) {
      emit notifyErrorMsg(tr("您的设备与注册不符，请联系400客服热线"));
    } else if (retcode == E_RC_EXPIRED_USER) {
      emit notifyErrorMsg(tr("账号过期，请联系客服"));
    } else if (retcode == E_RC_IP_IN_BLACKLIST) {
      emit notifyErrorMsg(tr("登录受限"));
    } else if (retcode == E_RC_NOSERVERLIST) {
      emit notifyErrorMsg(tr("读取服务器列表失败，请联系客服"));
    } else if (retcode == eFT_PL_FORCE_QUIT) {
      emit notifyErrorMsg(tr("您的Qeubee账号被踢,需要重新注销登录"));
    }
  }
}

void StartupDlg::onBtnClicked(int index) {
  if (index == Scan) {
    m_loginByPwd = !m_loginByPwd;
    if (m_loginByPwd) {
      m_loginModeBtn->setImgId("auth_login_desktop");
      m_scanWidget->hide();
      m_loginSettingWidget->show();
    } else {
      m_loginModeBtn->setImgId("auth_login_qrcode");
      QSize s = m_loginSettingWidget->size();
      m_loginSettingWidget->hide();
      m_scanWidget->setFixedSize(s);
      m_scanWidget->show();
    }
  }
}

void StartupDlg::updateServerList() {
  m_cbServers->clear();
  auto& servers = QuoteServerInfo::instance().serverGroups();
  int index = 0;
  for (auto server : servers) {
    m_cbServers->addItem(QString::fromStdWString(server.name));
    m_cbServers->setItemData(index, index > 0 ? VeryBad : Good,
                             Qt::DecorationRole);
    index++;
  }
  m_cbServers->setItemData(0, true, Qt::DisplayPropertyRole);
  // TODO: 测速
  QuoteServerInfo::instance().setCurrentServer(servers[0].index,
                                               servers[0].servers[0].index);
}

#include <QToolTip>
void StartupDlg::login() {
  QString userName = m_editUser->text();
  QString userPwd = m_editPwd->text();
  if (userName.isEmpty()) {
    showErrorMsg(tr("账号不能为空"));
    return;
  }

  if (userPwd.isEmpty()) {
    showErrorMsg(tr("密码不能为空"));
    return;
  }

  saveCfg();
  m_loginSettingWidget->setEnabled(false);

  m_loginBtn->setLoginState(true);
  CAuthLogin::instance().login();
}

void StartupDlg::showErrorMsg(const QString& err) {
  if (!m_errTips) {
    m_errTips = new FadeTips(this);
    m_errTips->setMargin(32, 16);
  }

  QRect rect = this->geometry();
  int x = rect.x() + rect.width() / 2 - m_errTips->width() / 2;
  int y = rect.y() + rect.height() / 2 - m_errTips->height();
  m_errTips->hide();
  m_errTips->setMessage(err);
  m_errTips->move(x, y);
  m_errTips->show();
}

void StartupDlg::onClearPwd() { m_editPwd->clear(); }

void StartupDlg::saveCfg() {
  LoginUserInfo lui;
  lui.strUser = m_editUser->text().toStdString();
  lui.strPwd = m_editPwd->text().toStdString();
  lui.savePwd = m_rememberPwd->isSelected();
  lui.autoRun = m_autoStart->isSelected();
  QuoteServerInfo::instance().updateUserInfo(lui);
}
